103

     # loguru - подключение и использование

Содержание

  1. Первоначальная настройка. Основы
  2. Распределение логирования по разным файлам
  3. Изменение дефолтного формата
  4. Автоматическое удаление логов
  5. Изменение уровня логирования

1. Первоначальная настройка. Основы

Установка зависимости

pip3 install loguru

Импортируем модуль в главном файле (напр., main.py) и определяем настройки логирования:

1
2
from loguru import logger
logger.add("logs/application.log", format="{time} {level} {message}", level="DEBUG", retention = "1 day")

Директория logs будет автоматически создана библиотекой loguru, если не существует.

Прописываем логирование в main.py, используя вместо print("Программа запущена"):

1
logger.debug("Программа запущена")

Для добавления логирования в другие скрипты, просто дополнительно импортируем модуль:

another_script.py

1
2
from loguru import logger
logger.debug("Запущен модуль another_script.py")

yet_one_script.py

1
2
from loguru import logger
logger.debug("Запущен модуль yet_one_script.py")

В таком случае (когда мы не переопределяем настройки) логирование будет работать согласно параметрам, указанным в файле main.py, то есть вся информация из всех скриптов будет записываться в logs/application.log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# main.py
from loguru import logger
from another_script import run_another_script
from yet_one_script import run_yet_one_script

logger.add("logs/application.log", format="{time} {level} {message}", level="DEBUG", retention = "1 day")
logger.debug("Программа запущена")

run_another_script()
run_yet_one_script()

# another_script.py
from loguru import logger

def run_another_script():
    logger.debug("Запущен модуль another_script.py")

# yet_one_script.py
from loguru import logger

def run_yet_one_script():   
    logger.debug("Запущен модуль yet_one_script.py")

2024-01-20 16:14:46.322 | DEBUG    | __main__:<module>:6 - Программа запущена
2024-01-20 16:14:46.323 | DEBUG    | another_script:run_another_script:4 - Запущен модуль another_script.py
2024-01-20 16:14:46.323 | DEBUG    | yet_one_script:run_yet_one_script:4 - Запущен модуль yet_one_script.py

2. Распределение логирования по разным файлам

Если же требуется писать логи каждого скрипта в самостоятельный файл, то настройки требуется переопределить.

Если мы будем добавлять настройки в каждый самостоятельный модуль, напр.:

1
2
3
4
5
6
7
# yet_one_script.py
from loguru import logger

logger.add("logs/other.log", format="{time} {level} {message}", level="DEBUG", retention = "1 day")

def run_yet_one_script():   
    logger.debug("Запущен модуль yet_one_script.py")

То у нас просто появится много файлов под разными именами (logs/application.log, logs/other.log), которые будут дублировать друг друга. Далее показан пример, как можно разнести логи по разным файлам / прописать разные настройки:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# main.py
from loguru import logger
from another_script import run_another_script
from yet_one_script import run_yet_one_script

logger.add("logs/application.log", filter=lambda record: record["extra"].get("name") == "application",enqueue=True,catch=True, format="{time} {level} {message}", level="DEBUG", retention = "1 day"
)

logger_app = logger.bind(name="application")

logger_app.debug("Программа запущена")

run_another_script()
run_yet_one_script()

# another_script.py
from loguru import logger

logger.add("logs/another_script.log", filter=lambda record: record["extra"].get("name") == "another_script", format="{time} {level} {message}", level="DEBUG", retention = "1 day")

logger_another = logger.bind(name="another_script")

def run_another_script():
    logger_another.debug("Запущен модуль another_script.py")

# yet_one_script.py
from loguru import logger

logger.add("logs/yet_one_script.log", filter=lambda record: record["extra"].get("name") == "yet_one_script", format="{time} {level} {message}", level="DEBUG", retention = "1 day")

logger_yet = logger.bind(name="yet_one_script")

def run_yet_one_script():   
    logger_yet.debug("Запущен модуль yet_one_script.py")

В итоге появятся самостоятельные файлы для каждого скрипта, содержащие инфомацию только из этого скрипта:

├── logs
│   ├── another_script.log
│   ├── application.log
│   └── yet_one_script.log

3. Изменение дефолтного формата

Сбрасываем исходные настройки и прописываем своё форматирование через format.

1
2
3
4
5
logger.remove()
logger.add("logs/server.log", 
           format="<lvl>[</lvl><c>{time:DD.MM.YYYY HH:mm:ss.SSS}</c><lvl>]</lvl> <lvl>{message}</lvl>",
           level="INFO"
           )

В результате чего лог будет иметь следующий вид:

1
2
3
4
[20.01.2024 00:01:02.967] Поиск файлов менее 3072 Кб
[20.01.2024 00:01:02.969] Удаление файла по размеру: '/home/dao2/Видео/rtsp_recorder/2024-01-20_00:00:47.mp4'
[20.01.2024 00:01:02.969] Размер: '1327' Kb
[20.01.2024 00:01:02.969] Причина: размер меньше  '3072' Kb.

4. Автоматическое удаление логов

Применив следующий конфиг:

1
2
3
4
5
6
7
8
logger.remove()
logger.add("logs/server.log", 
           format="<lvl>[</lvl><c>{time:DD.MM.YYYY HH:mm:ss.SSS}</c><lvl>]</lvl> <lvl>{message}</lvl>",
           level="INFO",
           retention="1 days",
           rotation = "00:01",
           compression="zip"
           )
  • логи будут храниться в файле logs/server.log
  • каждую ночь в 00:01 будет создаваться новый файл server.log, а предыдущая информация будет храниться в зазипованном файле (напр., server.2024-01-19_00-01-12_281803.log.zip) и удалена через 1 день.

5. Изменение уровня логирования

Во время написания кода нам в любом случае потребуется добавлять логирование для анализа ошибок, данное логирование можно сохранять под уровнем DEBUG. При написании нового скрипта или класса можно добавлять одну строку кода под уровнем INFO, чтобы было общее представление, как работает программа без детального анализа кода.

Тем самым, закончив разработку, мы можем просто сменить уровень логирования с debug на info, лишив себя необходимости удаления излишнего логировния / мусора. А при анализе проблем в будущем можем переключиться снова на DEBUG.

Важно:

  • логирование на уровне INFO выводит сообщения, объявляемые на всех уровнях кроме debug, а именно:

    • logger.critical
    • logger.error
    • logger.info
    • logger.success
    • logger.warning
  • логирование на уровне DEBUG выводит абсолютно все сообщения (все уровни)

  • остальные уровни (CRITICAL, ERROR, SUCCESS, WARNING) выводят только себя и не показывают какой-либо другой уровень.

Итого, у нас есть проект:

├── another_script.py
├── config.py
├── main.py
└── yet_one_script.py

В config.py мы прописываем используемый уровень логирования:

log_level="INFO"

В main.py прописываем проверку, что переменная log_level равна одному из значений:

  • CRITICAL
  • DEBUG
  • ERROR
  • INFO
  • SUCCESS
  • WARNING
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
try:
    allowed_values = ["CRITICAL", "DEBUG", "ERROR", "INFO", "SUCCESS", "WARNING"]
    if config.log_level.upper() not in allowed_values:
        print('Файл config.py должен содержать переменную с одним из значений:')
        print(f"{allowed_values}")
        print('напр: log_level="INFO"')
        exit()
except:
    print('Файл config.py должен содержать переменную с одним из значений:')
    print(f"{allowed_values}")
    print('напр: log_level="INFO"')
    exit()

Теперь, меняя значение переменной log_level="INFO", мы можем переключаться между уровнями логирования:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# config.py
log_level="INFO"

# main.py
from loguru import logger
import sys

from another_script import run_another_script
from yet_one_script import run_yet_one_script
import config

try:
    allowed_values = ["CRITICAL", "DEBUG", "ERROR", "INFO", "SUCCESS", "WARNING"]
    if config.log_level.upper() not in allowed_values:
        print('Файл config.py должен содержать переменную с одним из значений:')
        print(f"{allowed_values}")
        print('напр: log_level="INFO"')
        exit()
except:
    print('Файл config.py должен содержать переменную с одним из значений:')
    print(f"{allowed_values}")
    print('напр: log_level="INFO"')
    exit()

logger.remove()
logger.add(
    "logs/application.log",
    format="{time} {level} {message}", 
    retention = "1 day",
    level=config.log_level.upper()
)

logger.error("Ошибок нет")
logger.warning("Сейчас запустится info-логирование")
logger.info("Логирование в config.py = INFO")

logger.debug("Логирование в config.py = DEBUG")
run_another_script()
logger.debug("Скрипт run_another_script отработал")
run_yet_one_script()
logger.debug("Скрипт run_yet_one_script отработал")


# another_script.py
from loguru import logger

def run_another_script():
    logger.info("Запущен модуль another_script.py")
    logger.debug("Запущен модуль another_script.py")


# yet_one_script.py
from loguru import logger

def run_yet_one_script():   
    logger.info("Запущен модуль yet_one_script.py")
    logger.debug("Запущен модуль yet_one_script.py")

Выполнив данный код, в файле logs/application.log отобразятся следующие строки:

1
2
3
4
5
2024-01-20T18:59:26.269211+0300 ERROR Ошибок нет
2024-01-20T18:59:26.269314+0300 WARNING Сейчас запустится info-логирование
2024-01-20T18:59:26.269346+0300 INFO Лоигрование в config.py = INFO
2024-01-20T18:59:26.269390+0300 INFO Запущен модуль another_script.py
2024-01-20T18:59:26.269426+0300 INFO Запущен модуль yet_one_script.py

Если же активировать уровень debug, то лог изменится на:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
2024-01-20T19:00:11.596537+0300 ERROR Ошибок нет
2024-01-20T19:00:11.596891+0300 WARNING Сейчас запустится info-логирование
2024-01-20T19:00:11.596989+0300 INFO Лоигрование в config.py = INFO
2024-01-20T19:00:11.597040+0300 DEBUG Лоигрование в config.py = DEBUG
2024-01-20T19:00:11.597097+0300 INFO Запущен модуль another_script.py
2024-01-20T19:00:11.597143+0300 DEBUG Запущен модуль another_script.py
2024-01-20T19:00:11.597186+0300 DEBUG Скрипт run_another_script отработал
2024-01-20T19:00:11.597233+0300 INFO Запущен модуль yet_one_script.py
2024-01-20T19:00:11.597296+0300 DEBUG Запущен модуль yet_one_script.py
2024-01-20T19:00:11.597336+0300 DEBUG Скрипт run_yet_one_script отработал

Можно также не писать в файл, а выводить лог в консоль:

1
2
3
4
5
6
7
import sys
logger.add(
    sys.stdout, # <= указываем вместо файла
    format="{time} {level} {message}", 
    retention = "1 day",
    level=config.log_level.upper()
)